var WHITE = 0;
var BLACK = 1;
var NULL_COLOR = 2;
var COLOR_TEXT = ["White", "Black"];
var OPPOSITE_COLOR = [BLACK, WHITE, NULL_COLOR];

var AREA_LIMIT = 1.0/128; //XXX

var DBG_MODE = false;

var TOP = 0;
var BOTTOM = 1;
var LEFT = 2;
var RIGHT = 3;
var UNKNOWN_SIDE = 4;
var SIDE_TEXT = ["Top", "Bottom", "Left", "Right"];

var OPPOSITE_SIDE = [BOTTOM, TOP, RIGHT, LEFT];
var ORTHOGONAL_SIDE = [RIGHT, RIGHT, BOTTOM, BOTTOM];
var ALL_ORTHOGONAL_SIDES = [[LEFT, RIGHT], [LEFT, RIGHT], [TOP, BOTTOM], [TOP, BOTTOM]];

var HORIZONTAL = 0;
var VERTICAL = 1;
var UNKNOWN_DIR = 2;
var DIR_TEXT = ["Horizontal", "Vertical"];

// side to direction
var DIR = [HORIZONTAL, HORIZONTAL, VERTICAL, VERTICAL];
var OPPOSITE_DIR = [VERTICAL, HORIZONTAL];
/*
// corners
var TOP_LEFT = 0;
var TOP_RIGHT = 1;
var BOTTOM_LEFT = 2;
var BOTTOM_RIGHT = 3;
*/
var TINY = 0.0000001;

var START_X = 0;
var START_Y = 1;
var END_X = 2;
var END_Y = 3;


function Piece (startX, startY, x, y, color) {
  this.init(startX, startY, x, y, color);
}

Piece.prototype.init = function(startX, startY, x, y, color) {
  if (DBG_MODE) {
    assertParams(arguments, [Rational, Rational, Rational, Rational, Number]);
    assert(color == WHITE || color == BLACK);
  }
  this.start = [startX, startY];
  this.end = [startX.add(x), startY.add(y)];
  this.length = [x, y];
  this.x = x;
  this.y = y;
  this.color = color;
}

Piece.prototype.isValid = function(x, y) {

  // make sure the piece is square or 2x1 ratio
  return x.equals(y) ||
         x.equals(y.half()) ||
         x.equals(y.twice());
};


Piece.prototype.sideSize = function(dir) {
  assert(dir == HORIZONTAL || dir == VERTICAL);
  return this.length[dir];
}

Piece.prototype.getStart = function(dir) {
  assert(dir == HORIZONTAL || dir == VERTICAL);
  return this.start[dir];
}

Piece.prototype.getEnd = function(dir) {
  assert(dir == HORIZONTAL || dir == VERTICAL);
  return this.end[dir];
}


Piece.prototype.canSplit = function(direction) {
  var x = this.x;
  var y = this.y;
  if (direction === HORIZONTAL) {
    y = y.half();
  } else {
    x = x.half();
  }
  return (this.isValid(x, y));
}

Piece.prototype.getMiddle = function(direction) {
  assert(this.canSplit(direction));
  if (direction === HORIZONTAL) {
    return this.start[VERTICAL].add(this.y.half());
  } else {
    return this.start[HORIZONTAL].add(this.x.half());
  }
}

Piece.prototype.swap = function() {
  this.color = OPPOSITE_COLOR[this.color];
}

Piece.prototype.area = function() {
  return 1.0 * this.x.top * this.y.top / (this.x.bot * this.x.bot);
}

Piece.prototype.samePosition = function (p) {
  return this.start[HORIZONTAL].equals(p.start[HORIZONTAL]) &&
         this.start[VERTICAL].equals(p.start[VERTICAL]) &&
         this.x.equals(p.x) && this.y.equals(p.y);
}

toTest.push(Piece);


Piece.prototype.test = function() {
  var a = new Rational(1,6);
  var b = new Rational(1,4);
  assert(this.isValid(a, a));
  assert(this.isValid(a, a.half()));
  assert(this.isValid(a, a.twice()));
  assert(!this.isValid(a, b));
  var p = new Piece (ZERO, ZERO, a, a.half(), WHITE);
  assert(p.sideSize(DIR[BOTTOM]).equals(a));
  assert(p.sideSize(DIR[TOP]).equals(a));
  assert(p.sideSize(DIR[LEFT]).equals(a.half()));
  assert(p.sideSize(DIR[RIGHT]).equals(a.half()));
  assert(new Piece(ZERO, ZERO, a, a, WHITE).canSplit(HORIZONTAL));
  assert(new Piece(ZERO, ZERO, a, a.half(), WHITE).canSplit(VERTICAL));
  assert(!new Piece(ZERO, ZERO, a, a.half(), WHITE).canSplit(HORIZONTAL));
  assert(new Piece(ZERO, ZERO, a.half(), a, WHITE).canSplit(HORIZONTAL));
  assert(!new Piece(ZERO, ZERO, a.half(), a, WHITE).canSplit(VERTICAL));
};
